package com.mes.biz.service.impl;

import com.mes.biz.domain.*;
import com.mes.biz.mapper.*;
import com.mes.biz.service.BizPayableService;
import com.mes.biz.service.BizPaymentBillService;
import com.mes.biz.service.BizPaymentDetailService;
import com.mes.biz.service.BizPaymentService;
import com.mes.common.core.domain.BaseEntity;
import com.mes.common.core.service.BaseServiceImpl;
import com.mes.common.exception.BizException;
import com.mes.common.utils.SecurityUtils;
import com.mes.system.common.SysErrorCode;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Random;

/**
 * 收款单Service业务层处理
 * @author hwg
 * @email hwg
 * @date 2023-04-30
 */
@Service
@Transactional(readOnly = true)
public class BizPaymentServiceImpl extends BaseServiceImpl<BizPaymentMapper, BizPayment> implements BizPaymentService {

    @Resource
    private BizCustomerPayableMapper bizCustomerPayableMapper;
    @Resource
    private BizPaymentMapper bizPaymentMapper;
    @Resource
    private BizCustomerAccountMapper bizCustomerAccountMapper;
    @Resource
    private BizOrderMapper bizOrderMapper;

    @Resource
    private BizCustomerPayableDetailMapper bizCustomerPayableDetailMapper;
    @Resource
    private BizPaymentBillService bizPaymentBillService;
    @Resource
    private BizPaymentDetailService bizPaymentDetailService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createPayment(BizPayment bizPayment) {
        Random random = new Random();
        //把随机生成的数字转成字符串
        String str = String.valueOf(random.nextInt(9));
        for (int i = 0; i < 5; i++) {
            str += random.nextInt(9);
        }
        bizPayment.setPayCode("PAY-" + str);
        String tenantId = SecurityUtils.getTenantId();
        bizPayment.setTenantId(tenantId);
        boolean res = save(bizPayment);
        if(res) {
            BizCustomerPayable bizCustomerPayable = bizCustomerPayableMapper.getBizCustomerPayableByCustomerId(bizPayment.getCustomerId());
//            if(bizCustomerPayable.getPayAmount().add(bizPayment.getPayAmount()).compareTo(bizCustomerPayable.getTotalAmount()) > 0) {
//                throw new BizException("收款金额超过应收总额！");
//            }
            BigDecimal amount = bizPayment.getPayableDetails().stream().map(BizCustomerPayableDetail::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal payAmount = bizPayment.getPaymentDetailList().stream().map(BizPaymentDetail::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if(amount.compareTo(payAmount) == 0) {
//                bizCustomerPayable.setPayAmount(bizCustomerPayable.getPayAmount().add(bizPayment.getPayAmount()));
//                bizCustomerPayable.setHasAmount(bizCustomerPayable.getTotalAmount().subtract(bizCustomerPayable.getPayAmount()));
//                bizCustomerPayableMapper.update(bizCustomerPayable);
                List<BizPaymentDetail> paymentDetails = bizPayment.getPaymentDetailList();
                for (BizPaymentDetail bizPaymentDetail : paymentDetails){
                    bizPaymentDetail.setPaymentId(bizPayment.getId());
                    bizPaymentDetail.setTenantId(tenantId);
                    bizPaymentDetailService.save(bizPaymentDetail);
                }
                List<BizCustomerPayableDetail> payableDetails = bizPayment.getPayableDetails();
                for (BizCustomerPayableDetail detail:payableDetails) {
                    BizPaymentBill bizPaymentBill=new BizPaymentBill();
                    bizPaymentBill.setPaymentId(bizPayment.getId());
                    bizPaymentBill.setCustomerId(detail.getCustomerId());
                    bizPaymentBill.setCustomerId(detail.getCustomerId());
                    bizPaymentBill.setOrderNumber(detail.getOrderNumber());
                    bizPaymentBill.setTotalAmount(detail.getTotalAmount());
                    bizPaymentBill.setPayAmount(detail.getAmount());
                    bizPaymentBill.setLinkId(detail.getId());
                    bizPaymentBill.setRemark(detail.getRemark());
                    bizPaymentBill.setOrderProductId(detail.getOrderProductId());
                    bizPaymentBill.setTenantId(tenantId);
                    bizPaymentBill.setSort(detail.getSort());
                    bizPaymentBillService.save(bizPaymentBill);

//                    if (detail.getPayAmount() != null){
//                        detail.setPayAmount(detail.getPayAmount().add(detail.getAmount()));
//                    }else {
//                        detail.setPayAmount(detail.getAmount());
//                    }
//                    bizCustomerPayableDetailMapper.update(detail);
//                    BizOrder bizOrder = bizOrderMapper.getBizOrderByOrderNumber(detail.getOrderNumber());
//                    bizOrder.setCollectedAmount(bizOrder.getCollectedAmount().add(detail.getAmount()));
//                    bizOrderMapper.update(bizOrder);
                }
//                BizCustomerAccount bizCustomerAccountInfo = bizCustomerAccountMapper.getBizCustomerAccountInfo(bizPayment.getAccountCode());
//                bizCustomerAccountInfo.setPayAmount(payAmount);
//                if(payAmount.compareTo(bizCustomerAccountInfo.getTotalAmount()) == 0) {
//                    bizCustomerAccountInfo.setStatus(BaseEntity.SUCCESS_STATUS);
//                }else {
//                    bizCustomerAccountInfo.setStatus(BaseEntity.WAIT_STATUS);
//                }
//                bizCustomerAccountMapper.update(bizCustomerAccountInfo);
            }else {
                throw new BizException("本次结算金额与收款金额不一致！");
            }
        }
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePayment(BizPayment bizPayment) {
        int update = bizPaymentMapper.update(bizPayment);
        if(update > 0) {
            BizCustomerPayable bizCustomerPayable = bizCustomerPayableMapper.getBizCustomerPayableByCustomerId(bizPayment.getCustomerId());
//            if(bizCustomerPayable.getPayAmount().add(bizPayment.getPayAmount()).compareTo(bizCustomerPayable.getTotalAmount()) > 0) {
//                throw new BizException("收款金额超过应收总额！");
//            }
            BigDecimal amount = bizPayment.getPaymentDetailList().stream().map(BizPaymentDetail::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal payAmount = bizPayment.getPaymentDetailList().stream().map(BizPaymentDetail::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if(amount.compareTo(payAmount) == 0) {
                List<BizPaymentDetail> paymentDetails = bizPayment.getPaymentDetailList();
                for (BizPaymentDetail bizPaymentDetail : paymentDetails){
                    bizPaymentDetail.setPaymentId(bizPayment.getId());
                    bizPaymentDetail.setTenantId(bizPayment.getTenantId());
                    bizPaymentDetailService.save(bizPaymentDetail);
                }

                List<BizPaymentBill> bizPaymentBills = bizPayment.getPaymentBillList();
                for (BizPaymentBill bizPaymentBill:bizPaymentBills) {
                    bizPaymentBill.setPaymentId(bizPayment.getId());
                    bizPaymentBill.setTenantId(bizPayment.getTenantId());
                    bizPaymentBillService.save(bizPaymentBill);
                }
            }else {
                throw new BizException("本次结算金额与收款金额不一致！");
            }
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deletePayment(String id) {
        BizPayment bizPayment = bizPaymentMapper.get(id);
//        String customerId = bizPayment.getCustomerId();
//        BigDecimal payAmount = bizPayment.getPayAmount();
        int delete = bizPaymentMapper.delete(bizPayment);
        if(delete > 0) {
//            BizCustomerPayable bizCustomerPayable = bizCustomerPayableMapper.getBizCustomerPayableByCustomerId(customerId);
//            bizCustomerPayable.setPayAmount(bizCustomerPayable.getPayAmount().subtract(payAmount));
//            bizCustomerPayable.setHasAmount(bizCustomerPayable.getHasAmount().add(payAmount));
//            bizCustomerPayableMapper.update(bizCustomerPayable);

            bizPaymentDetailService.deleteBizPaymentDetailByPaymentId(id);
            bizPaymentBillService.deleteBizPaymentBillByPaymentId(id);
//            List<BizPaymentBill> bizPaymentBills = bizPaymentBillService.selectByPaymentId(id);
//            if (bizPaymentBills!=null && bizPaymentBills.size()>0){
//                for (BizPaymentBill bizPaymentBill : bizPaymentBills){
//                    BizCustomerPayableDetail detail = bizCustomerPayableDetailMapper.get(bizPaymentBill.getLinkId());
//                    detail.setPayAmount(detail.getPayAmount().subtract(bizPaymentBill.getPayAmount()));
//                    bizCustomerPayableDetailMapper.update(detail);
//                    BizOrder bizOrder = bizOrderMapper.getBizOrderByOrderNumber(detail.getOrderNumber());
//                    bizOrder.setCollectedAmount(bizOrder.getCollectedAmount().subtract(bizPaymentBill.getPayAmount()));
//                    bizOrderMapper.update(bizOrder);
//                }
//                BizCustomerAccount bizCustomerAccountInfo = bizCustomerAccountMapper.getBizCustomerAccountInfo(bizPayment.getAccountCode());
//                bizCustomerAccountInfo.setPayAmount(bizCustomerAccountInfo.getPayAmount().subtract(payAmount));
//                if(bizCustomerAccountInfo.getPayAmount().compareTo(BigDecimal.ZERO) == 0) {
//                    bizCustomerAccountInfo.setStatus(BaseEntity.WAIT_HAHDLE);
//                }else {
//                    bizCustomerAccountInfo.setStatus(BaseEntity.WAIT_STATUS);
//                }
//                bizCustomerAccountMapper.update(bizCustomerAccountInfo);
//            }
            return true;
        }
        return false;
    }

    @Override
    public List<BizPayment> getByAccountCode(String accountCode) {
        return mapper.getByAccountCode(accountCode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean auditPayment(String id) {
        BizPayment bizPayment = super.get(id.split(":")[0]);
        bizPayment.setStatus((id.split(":")[1]));
        int update = bizPaymentMapper.update(bizPayment);
        if(update > 0) {
            //实收金额和抹零金额
            BigDecimal actualAmount=BigDecimal.ZERO;
            BigDecimal wipeAmount=BigDecimal.ZERO;
            List<BizPaymentDetail> paymentDetails = bizPaymentDetailService.selectByPaymentId(bizPayment.getId());
            if (paymentDetails != null && paymentDetails.size()>0){
                for (BizPaymentDetail paymentDetail : paymentDetails) {
                    if ("抹零".equals(paymentDetail.getPayAccount())){
                        wipeAmount=wipeAmount.add(paymentDetail.getPayAmount());
                    }else {
                        actualAmount=actualAmount.add(paymentDetail.getPayAmount());
                    }
                }

            }
            BizCustomerPayable bizCustomerPayable = bizCustomerPayableMapper.getBizCustomerPayableByCustomerId(bizPayment.getCustomerId());
            if ("1".equals(bizPayment.getStatus())){
//                if(bizCustomerPayable.getPayAmount().add(bizPayment.getPayAmount()).compareTo(bizCustomerPayable.getTotalAmount()) > 0) {
//                    throw new BizException("收款金额超过应收总额！");
//                }
                bizCustomerPayable.setPayAmount(bizCustomerPayable.getPayAmount().add(bizPayment.getPayAmount()));
                bizCustomerPayable.setHasAmount(bizCustomerPayable.getTotalAmount().subtract(bizCustomerPayable.getPayAmount()));
                bizCustomerPayableMapper.update(bizCustomerPayable);
                List<BizPaymentBill> bizPaymentBills = bizPaymentBillService.selectByPaymentId(bizPayment.getId());
                if (bizPaymentBills != null && bizPaymentBills.size() > 0){
                    for (BizPaymentBill bizPaymentBill : bizPaymentBills){
                        BizCustomerPayableDetail detail = bizCustomerPayableDetailMapper.get(bizPaymentBill.getLinkId());
                        if (detail.getPayAmount() != null){
                            detail.setPayAmount(detail.getPayAmount().add(bizPaymentBill.getPayAmount()));
                        }else {
                            detail.setPayAmount(bizPaymentBill.getPayAmount());
                        }
                        bizCustomerPayableDetailMapper.update(detail);
                        if ("0".equals(detail.getType())){
                            BizOrder bizOrder = bizOrderMapper.getBizOrderByOrderNumber(bizPaymentBill.getOrderNumber());
                            bizOrder.setCollectedAmount(bizOrder.getCollectedAmount().add(bizPaymentBill.getPayAmount()));
                            bizOrderMapper.update(bizOrder);
                        }

                    }
                }

                BizCustomerAccount bizCustomerAccountInfo = bizCustomerAccountMapper.getBizCustomerAccountInfo(bizPayment.getAccountCode());
                bizCustomerAccountInfo.setPayAmount(bizCustomerAccountInfo.getPayAmount().add(bizPayment.getPayAmount()));
                bizCustomerAccountInfo.setActualAmount(bizCustomerAccountInfo.getActualAmount().add(actualAmount));
                bizCustomerAccountInfo.setWipeAmount(bizCustomerAccountInfo.getWipeAmount().add(wipeAmount));
                if(bizPayment.getPayAmount().compareTo(bizCustomerAccountInfo.getTotalAmount()) == 0) {
                    bizCustomerAccountInfo.setStatus(BaseEntity.SUCCESS_STATUS);
                }else {
                    bizCustomerAccountInfo.setStatus(BaseEntity.WAIT_STATUS);
                }
                bizCustomerAccountMapper.update(bizCustomerAccountInfo);
            }else {
                bizCustomerPayable.setPayAmount(bizCustomerPayable.getPayAmount().subtract(bizPayment.getPayAmount()));
                bizCustomerPayable.setHasAmount(bizCustomerPayable.getTotalAmount().subtract(bizCustomerPayable.getPayAmount()));
                bizCustomerPayableMapper.update(bizCustomerPayable);

                List<BizPaymentBill> bizPaymentBills = bizPaymentBillService.selectByPaymentId(bizPayment.getId());
                if (bizPaymentBills!=null && bizPaymentBills.size()>0){
                    for (BizPaymentBill bizPaymentBill : bizPaymentBills){
                        BizCustomerPayableDetail detail = bizCustomerPayableDetailMapper.get(bizPaymentBill.getLinkId());
                        detail.setPayAmount(detail.getPayAmount().subtract(bizPaymentBill.getPayAmount()));
                        bizCustomerPayableDetailMapper.update(detail);
                        if ("0".equals(detail.getType())){
                            BizOrder bizOrder = bizOrderMapper.getBizOrderByOrderNumber(detail.getOrderNumber());
                            bizOrder.setCollectedAmount(bizOrder.getCollectedAmount().subtract(bizPaymentBill.getPayAmount()));
                            bizOrderMapper.update(bizOrder);
                        }
                    }
                    BizCustomerAccount bizCustomerAccountInfo = bizCustomerAccountMapper.getBizCustomerAccountInfo(bizPayment.getAccountCode());
                    bizCustomerAccountInfo.setPayAmount(bizCustomerAccountInfo.getPayAmount().subtract(bizPayment.getPayAmount()));
                    bizCustomerAccountInfo.setActualAmount(bizCustomerAccountInfo.getActualAmount().subtract(actualAmount));
                    bizCustomerAccountInfo.setWipeAmount(bizCustomerAccountInfo.getWipeAmount().subtract(wipeAmount));
                    if(bizCustomerAccountInfo.getPayAmount().compareTo(BigDecimal.ZERO) == 0) {
                        bizCustomerAccountInfo.setStatus(BaseEntity.WAIT_HAHDLE);
                    }else {
                        bizCustomerAccountInfo.setStatus(BaseEntity.WAIT_STATUS);
                    }
                    bizCustomerAccountMapper.update(bizCustomerAccountInfo);
                }
            }

        }
        return false;
    }
}
